# python 基础
from public import print_1

print_1('数据类型总结')
"""
（1）数字（number）6

①长整型（int）

②浮点型（float）

③复数（complex）

④布尔型（bool）

（2）字符串（string）13、14

（3）列表（list）15

（4）元组（tuple）16

（5）字典（dictionary）17

（6）集合（set）18
"""

print_1('关键词', True)
import keyword
print(keyword.kwlist)

print_1('格式化输出（format 函数）')
str1 = "π is {:.2f}".format(3.1415926)  # 保留两位小数
print(str1)

str1 = "{:,}".format(100000000)  # 给数字加千位符
print(str1)

s1 = "{:b}".format(8)     # 将数字8转换为二进制
print(s1)
s2 = "{:o}".format(8)     # 将数字8转换为八进制
print(s2)
s3 = "{:x}".format(12)    # 将数字12转换为十六进制
print(s3)

print_1('算术运算符', True)
# 算术运算符
# 算术运算符包括：加（+）、减（-）、乘（*）、除（/）、取模（%）、幂（**）和取整除（//）

# 比较运算符
# 比较运算符包括：等于（==）、不等于（!=）、大于（>）、小于（<）、大于等于（>=）和小于等于（<=）

# 赋值运算符
# 运算符	 含义	            实例
# =	    简单的赋值运算符	    c = a + b 将 a + b 的运算结果赋值为 c
# +=	加法赋值运算符	        c += a 等效于 c = c + a
# -=	减法赋值运算符	        c -= a 等效于 c = c - a
# *=	乘法赋值运算符     	c *= a 等效于 c = c * a
# /=	除法赋值运算符     	c /= a 等效于 c = c / a
# %=	取模赋值运算符	        c %= a 等效于 c = c * a
# **=	幂赋值运算符      	c **= a 等效于 c = c ** a
# //=	取整除赋值运算符	    c //= a 等效于 c = c // a

# 位运算符
# 运算符	含义	            描述	                                                                实例
# &	    按位与运算符	    参与运算的两个值,如果两个相应位都为 1，则该位的结果为 1，否则为 0	            (a & b) 输出结果 12 ，二进制解释：0000 1100
# |	    按位或运算符	    只要对应的二个二进位有一个为 1 时，结果位就为 1	                            (a | b) 输出结果 61 ，二进制解释： 0011 1101
# ^	    按位异或运算符	    当两对应的二进位相异时，结果为 1	                                        (a ^ b) 输出结果 49 ，二进制解释：0011 0001
# ~	    按位取反运算符	    对数据的每个二进制位取反，即把 1 变为 0，把 0 变为 1。~x 类似于 -x-1	        (~a ) 输出结果 -61 ，二进制解释： 1100 0011， 在一个有符号二进制数的补码形式。
# <<	左移动运算符	    运算数的各二进位全部左移若干位，由“<<”右边的数指定移动的位数，高位丢弃，低位补0	a << 2 输出结果 240 ，二进制解释： 1111 0000
# >>	右移动运算符	    把“>>”左边的运算数的各二进位全部右移若干位，“>>”右边的数指定移动的位数	        a >> 2 输出结果 15 ，二进制解释： 0000 1111


print_1('字符串操作',True)
# 字符串的索引
# Python 中的字符串有两种索引方式，从左往右以 0 开始，从右往左以 -1 开始。
# 0   1   2   3   4   5
# -6 -5   -4  -3  -2  -1
# p   y   t   h   o   n

# 字符串的检索
# 语法格式为：str.find(sub, start, end)
# str：原字符串；
# sub：要查找的目标字符串；
# start：开始检索的位置所对应的索引值；如果不指定，则默认从头开始检索；
# end：结束检索的位置所对应的索引值；如果不指定，则默认一直检索到结尾。
print_1('字符串的检索')
str1 = "abcdefghijklmn"
print(str1.find("abc"))
print(str1.find("lmn"))
print(str1.find("n", 5, 13))

# 检索字符串包含目标字符串的次数
# count 函数用于查找目标字符串在另一字符串中出现的次数，指定 start 和 end 的范围（顾头不顾尾），如果检索的字符串不存在，则返回 0，否则返回出现的次数，语法格式为：str.count(sub, start, end)

# 字符串的替换
# 语法格式为：str.replace(old_str, new_str, num)

print_1('字符串的删除')
# strip 函数用于删除字符串头、尾指定的字符（默认为空格）或字符序列 str.strip([chars]),
# lstrip 函数用于删除字符串左侧指定的字符
# rstrip 函数用于删除字符串右侧指定的字符
str1 = "    123123123\n\t\r"
print(str1.strip())
str2 = "******123******"
print(str2.strip("*"))

print_1('字符串的截取')
# 字符串的截取的语法格式为：str[start:end:step]
# 其中 start 表示开始检索的位置所对应的索引值，如果不指定，则默认从头开始检索；end 表示结束检索的位置所对应的索引值，如果不指定，则默认一直检索到结尾；step 表示步长，默认为 1；顾头不顾尾。
a = "shijiazhuang"
print(a[0])
print(a[5])
print(a[0:5])
print(a[0:8])
print(a[-5:-2])         # 起始位置是倒数第五位的 h，结束位置是倒数第二位的 n，顾头不顾尾
print(a[0:10:2])
print(a[:5])
print(a[5:])

print_1('字符串的分割')
# split 函数可以将一个字符串按照指定的分隔符切分成多个子串，这些子串会被保存到列表中（不包含分隔符），作为方法的返回值反馈回来，语法格式为：str.split(sep=" ",num)[n]
str1 = "www.nihao.com.cn"
print(str1.split("."))
print(str1.split("c"))
print(str1.split(".", 2))
print(str1.split(".", 2)[2])
a, b, c, d = str1.split(".")
print(a)
print(b)
print(c)
print(d)

print_1('字符串的合并')
# join 函数用于连接任意数量的字符串（包括要连接的元素字符串、元组、列表、字典），用新的目标分隔符连接，返回新的字符串，语法格式为："sep".join(sequence)
sequence = "H", "a", "p", "p", "y"
print("".join(sequence))
print(" ".join(sequence))
print("-".join(sequence))

print_1('字符串的编码和解码')
# encode 函数用于将 str 类型转换成 bytes 类型，这个过程也成为编码，语法格式为：str.encode(encoding="字符编码类型",errors="错误处理方式")
# decode 函数用于将 bytes 类型的二进制数据转换为 str 类型，这个过程也成为解码，语法格式为：bytes.decode(encoding="字符编码类型", errors="错误处理方式")

print_1('首字母大写')
str1 = "abCDef"
print(str1.capitalize())

print_1('字母全部大写')
str1 = "abCDef"
print(str1.upper())

print_1('字母全部小写')
str1 = "abCDef"
print(str1.lower())

print_1('字母大小写互换')
str1 = "abCDef"
print(str1.swapcase())

print_1('标题化')
# title 函数用于返回“标题化”的字符串，就是说所有单词的首个字母转化为大写，其余字母均为小写
print(str.title("tHe wOrLDwidE Web"))
print(str.title("北京luohu"))
str1 = "tHe wOrLDwidE Web"
print(str1.title())

print_1('字符串的检查')
# startswith 函数用于检查字符串是否是以指定子字符串开头，如果是则返回 True，否则返回 False。如果参数 start 和 end 指定值，则在指定范围内检查，语法格式为：str.startswith(substr[, start[, end]])
str1 = "abcdefg"
print(str1.startswith("abc"))
print(str1.startswith("efg"))
print(str1.startswith("abc", 0, 6))
print(str1.startswith("abc", 1, 5))

# endswith 函数用于检查字符串是否是以指定子字符串结尾，如果是则返回 True，否则返回 False。如果参数 start 和 end 指定值，则在指定范围内检查，语法格式为：str.endswith(substr[, start[, end]])

str1 = "abcdefg"
print(str1.endswith("abc"))
print(str1.endswith("efg"))
print(str1.endswith("efg", 0, 6))
print(str1.endswith("efg", 0, 7))
print(str1.endswith("efg", 1, 5))

print_1('检查字符串是否只由字母或文字组成')
# isalpha 函数
str1 = "abcdefg"
str2 = "我很帅"
str3 = "hello你好"
str4 = "hello 你好"
str5 = "hello_你好"
str6 = "hello你好!"
print(str1.isalpha())
print(str2.isalpha())
print(str3.isalpha())
print(str4.isalpha())
print(str5.isalpha())
print(str6.isalpha())

print_1('isdigit 函数、isdecimal 函数和 isnumeric 函数')
# isdigit 函数、isdecimal 函数和 isnumeric 函数均可用于检查字符串是否只由数字组成，如果字符串只包含数字则返回 True，否则返回 False，它们的区别如下：
str1 = "1"
print(str1.isdigit())
print(str1.isdecimal())
print(str1.isnumeric())

print_1('istitle 函数')
# istitle 函数用于检查字符串中所有的单词拼写首字母是否为大写，且其他字母为小写
str1 = "Welcome To Beijing !"
str2 = "Welcome to beijing !"
print(str1.istitle())
print(str2.istitle())

print_1('isupper 函数')
# isupper 函数用于检查字符串中所有的字母是否都为大写，如果字符串中包含至少一个区分大小写的字符，并且所有这些（区分大小写的）字符都是大写，则返回 True，否则返回 False，语法格式为：str.isupper()

print_1('islower 函数')
# islower 函数用于检查字符串是否由小写字母组成，如果字符串中包含至少一个区分大小写的字符，并且所有这些（区分大小写的）字符都是小写，则返回 True，否则返回 False，语法格式为：str.islower()
print_1('isspace 函数')
# isspace 函数用于检查字符串是否只由空白字符组成，如果字符串中只包含空格，则返回 True，否则返回 False，语法格式为：str.isspace()
print_1('isalnum 函数')
# isalnum 函数用于检查字符串是否由字母和数字组成，如果 str 至少有一个字符并且所有字符都是字母或数字则返回 True，否则返回 False，语法格式为：str.isalnum()

print_1('列表',True)
print_1('返回列表中元素最小值和最大值')
# Python 中可以分别使用 max 函数和 min 函数查看列表中元素的最大值和最小值，语法格式为：max(listname)，min(listname)
print_1('返回列表中元素的总和')
# Python 中可以使用 sum 函数返回列表各元素的总和，语法格式为：sum(listname)
print_1('列表中元素的添加【增】')
# append 函数用于在列表的末尾追加元素
# extend 函数extend 函数不会把列表或者元祖视为一个整体，而是把它们包含的元素逐个添加到列表中
list1 = ["aa", "bb", "cc", "dd"]
list1.extend("ee")
print(list1)
list1.extend("10")
print(list1)
list1.extend("1e!")
print(list1)
list2 = ["ff", "gg", "hh"]
list1.extend(list2)
print(list1)
tuple1 = ("ii", "jj", "kk", "ll")
list1.extend(tuple1)
print(list1)
# insert 函数 insert 函数用于在列表中间某个位置插入元素，语法格式为：listname.insert(index, obj)

print_1('列表中元素的删除【删】')
# del
# pop 函数用来删除列表中指定索引处的元素
# remove 函数会根据元素本身的值来进行删除操作
list1 = [2, 36, 2, 7, "aa", "bb"]
list1.remove("aa")
print(list1)
# clear 函数clear 函数用来删除列表的所有元素，即清空列表，语法格式为：listname.clear()
print_1('列表中元素的查找【查】')
# count 函数用于统计某个元素在列表中出现的次数，语法格式为：listname.count(obj)
list1 = ["a", "b", "a", "b", 1, 2, 1, 1]
print(list1.count("c"))

# index 函数
# index 函数用于查找某个元素在列表中出现的位置（也就是索引）如果该元素不存在，则会导致 ValueError 错误，语法格式为：listname.index(obj, start, end)

# in，not in 成员运算符
# 成员运算符 in 和 not in 用于断列表中的某个元素是否存在，语法格式为：obj in listname 和 obj not in listname，obj 表示要查找的元素，listname 表示列表名称，如果表述正确，返回 True，否则返回 False。

print_1('列表中元素的排列【排】')
# sorted 函数sorted
# 函数作为 Python 内置函数之一，用于对序列（列表、元组、字典、集合、还包括字符串）进行排序，语法格式为：listname = sorted(iterable, key=None, reverse=False) ，print(listname)

# sort 函数
# sort 函数用于对原列表进行排序，语法格式为：listname.sort(key=None, reverse=False)，print(listname)，listname 表示指定的序列，key 参数可以自定义排序规则，reverse 参数指定以升序（False，默认）还是降序（True）进行排序。使用 sort 函数对列表进行排序，不返回值，直接在列表上操作，会改变原列表的值。

# reverse 函数
# reverse 函数用于对列表中的元素反向排序，语法格式为：listname.reverse()，listname 表示指定的序列，使用 reverse 函数对列表进行排序，不返回值，直接在列表上操作，会改变原列表的值。

print_1('元组',True)
"""
元组（tuple）是一个有序且不可更改的集合，允许重复。元组（tuple）是 Python 中一个重要的序列结构，和列表类似，元组也是由一系列按特定顺序排序的元素组成。元组和列表（list）的不同之处在于：列表的元素是可以更改的，包括修改元素值，删除和插入元素，所以列表是可变序列；而元组一旦被创建，它的元素就不可更改了，所以元组是不可变序列。

"""

print_1('元组的修改和删除')
# 通过连接多个元组的方式向元组中添加新元素
tuple1 = ("a", "b")
tuple2 = (1, 2, 3, 4)
tuple3 = tuple1 + tuple2
print(tuple3)
print(tuple1)
print(tuple2)

# 其他的操作和列表差不多

print_1('字典', True)
"""
Python 中字典（dict）是一种无序的、可变的序列，它的元素以“键值对（key-value）”的形式存储。相对地，列表（list）和元组（tuple）都是有序的序列，它们的元素在底层是挨着存放的。字典中，习惯将各元素对应的索引称为键（key），各个键对应的元素称为值（value），键及其关联的值称为“键值对”
"""

# 通过应用 dict 函数和 zip 函数，可将两个列表、元组、集合、字符串，甚至还可以将 range 区间转换为对应的字典，语法格式为：dictname = dict(zip(keys, values) )，其中
keys1 = ["two", "one", "three"]
values1 = (2, 1, 3)
values2 = range(0, 3)
dict1 = dict(zip(keys1, values1))
dict2 = dict(zip(keys1, values2))
print(dict1)
print(dict2)

# pop 函数用来删除指定的键值对，语法格式为：dictname.pop(key_obj)
# popitem 函数用来删除字典中最后一个键值对，语法格式为：dictname.popitem()，print(dictname)，

dict1 = {'one': 100, 'two': 200, 'three': [100, 200, 300]}
dict1.pop("one")
print(dict1)
dict2 = {'one': 100, 'two': 200, 'three': [100, 200, 300]}
dict2.popitem()
print(dict2)

# 判断字典中是否存在指定键值对
dict1 = {'语文': 85, '数学': 96, '英语': 92}
print("语文" in dict1)
print("物理" in dict1)

print_1('集合', True)
"""
集合（set）是一个无序的不重复元素序列，集合会将所有元素放在一对大括号 {} 中，相邻元素之间用 , 分隔，格式为：{element1, element2, ..., elementn}，其中，elementn 表示集合中的元素，个数没有限制。注意：

① 同一集合中，只能存储整型、浮点型、字符串、元组这些不可变的数据类型，无法存储列表、字典、集合这些可变的数据类型，否则 Python 解释器会抛出 TypeError 错误；

② 数据必须保证是唯一的，因为集合对于每种数据元素，只会保留一份；

③ 由于 Python 中的 set 集合是无序的，所以每次输出时元素的排序顺序可能都不相同。
"""
print_1('集合的创建')
# set 函数为 Python 的内置函数，其功能是将字符串、列表、元组、range 对象等可迭代对象转换成集合，语法格式为：setname = set(iteration)，其中，iteration 表示字符串、列表、元组、range 对象等数据，setname 表示集合名。
set1 = set("hello")
print(set1)
set2 = set([1, 2, "a"])
print(set2)
set3 = set({1: "a", 2: "b", 3: "c"})
print(set3)
set4 = set(range(0, 3))
print(set4)

print_1('集合的访问')
"""
由于集合中的元素是无序的，因此无法向列表那样使用下标访问元素。Python 中，访问集合元素最常用的方法是使用循环结构，将集合中的数据逐一读取出来，语法格式为
for element in setname:
    print(element)
"""

print_1('集合的删除')
"""
set1 = {1, 2, "a", "b", (1, 2, "a", "b")}
del set1
print(set1)
"""

print_1('集合中元素的添加')
set1 = {1, 2, "a", "b", (1, 2, "a")}
set1.add(3)
print(set1)

print_1('删除集合中的指定元素')
# remove 函数可以删除集合中的指定元素，语法格式为：setname.remove(element_obj)
set1 = {1, 2, "a", "b", (1, 2, "a")}
set1.remove("a")
print(set1)
set1.remove((1, 2, "a"))
print(set1)

# discard 函数discard 函数在移除一个不存在的元素时不会发生错误。
set2 = {1, 2, "a", "b", (1, 2, "a")}
set2.discard("a")
print(set2)
set2.discard(3)

print_1('删除集合中的所有元素')
# clear 函数可以删除集合中的所有元素，语法格式为：setname.clear()，其中，setname 表示集合名。
set1 = {1, 2, "a", "b", (1, 2, "a")}
set1.clear()
print(set1)

print_1('随机删除集合中的某个元素')
"""
pop 函数可以随机删除集合中的某个元素，语法格式为：setname.pop()，print(setname)，其中，setname 表示集合名。

① 如果集合的元素都是数字，删除时，删掉的是最小的数字，其余数字升序排列；

② 如果集合的元素是非数字，删除时，删掉的是随机的元素，其余元素随机排列；

③ 如果集合里既有数字又有非数字元素，删除时：

若删掉的是数字，则一定是删掉了最小的，其他数字升序排列，非数字元素随机排列；
若删掉的非数字，则一定是随机删掉了一个，其他数字升序排列，非数字则随机排列
"""
s1 = {4, 2, 1, 5}  # 集合里只有数字
s2 = {'你', '我', '他'}  # 集合里无数字
s3 = {3, 2, 4, '你', 'X'}  # 集合里既有数字又有非数字
s1.pop()  # 元素是数字时, 删除最小的数字, 其余数字升序排列
s2.pop()  # 元素非数字时, 随机删除一个元素, 其余元素随机排序
s3.pop()  # 元素既有数字又含非数字时, 如果删除的是数字, 则一定删最小的, 否则随机删除一个非数字元素
print(s1)
print(s2)
print(s3)  # 这个代码执行后, 输出的结果是随机的

print_1('集合的交集、并集、差集、对称差集运算')
"""
（1）集合的交集

集合的交集用于取两集合公共的元素，语法格式为：setname1 & setname2，其中，setname1 和 setname2 分别表示两个集合名。

（2）集合的并集

集合的并集用于取两集合全部的元素，语法格式为：setname1 | setname2，其中，setname1 和 setname2 分别表示两个集合名。

（3）集合的差集

集合的差集用于取一个集合中另一集合没有的元素，语法格式为：setname1 - setname2，其中，setname1 和 setname2 分别表示两个集合名，表示取 setname1 中 setname2 没有的元素。

（4）集合的对称差集

集合的对称差集用于取集合 1 和 2 中不属于 1&2 的元素，语法格式为：setname1 ^ setname2，其中，setname1 和 setname2 分别表示两个集合名，表示取 setname1 和 setname2 中不属于 setname1 & setname2 的元素。

"""
set1 = {4, 5, 6}
set2 = {6, 7, 8}
print(set1 & set2)
print(set1 | set2)
print(set1 - set2)
print(set2 - set1)
print(set1 ^ set2)

print_1('集合的基础操作')
print_1('difference 函数')
"""
difference 函数用于取 setname1 中有而 setname2 中没有的元素，给 setname3，语法格式为：setname3 = setname1.difference(setname2)，print(setname3)
"""
set1 = {4, 5, 6, 7}
set2 = {6, 7, 8}
set3 = set1.difference(set2)
print(set3)
"""
difference_update 函数用于从 setname1 中删除与 setname2 相同的元素，语法格式为：setname1.difference_update(setname2)，print(setname1)
"""
set1 = {4, 5, 6, 7}
set2 = {6, 7, 8}
set1.difference_update(set2)
print(set1)
"""
intersection 函数用于取 setname1 和 setname2 的交集，给 setname3，语法格式为：setname3 = setname1.intersection(setname2)，print(setname3)
"""
set1 = {4, 5, 6, 7}
set2 = {6, 7, 8}
set3 = set1.intersection(set2)
print(set3)

"""
difference_update 函数用于取 setname1和 setname2 的交集，并更新给 setname1，语法格式为：setname1.intersection_update(setname2)，print(setname1)
"""
set1 = {4, 5, 6, 7}
set2 = {6, 7, 8}
set3 = set1.intersection_update(set2)
print(set1)

"""
isdisjoint 函数用于判断两个集合是否包含相同的元素，如果没有返回 True，否则返回 False，语法格式为：setname1.isdisjoint(setname2)，其中，setname1 和 setname2 分别表示两个集合。
"""
set1 = {4, 5, 6, 7}
set2 = {6, 7, 8}
print(set1.isdisjoint(set2))

"""
issubset 函数用于判断 setname1 是否是 setname2 的子集，如果是返回 True，否则返回 False，语法格式为：setname1.issubset(setname2)，其中，setname1 和 setname2 分别表示两个集合。
"""
set1 = {6, 7}
set2 = {6, 7, 8}
print(set1.issubset(set2))

"""
issuperset 函数用于判断 setname1 是否包含 setname2，如果是返回 True，否则返回 False，语法格式为：setname1.issuperset(setname2)，其中，setname1 和 setname2 分别表示两个集合。
"""
set1 = {6, 7, 8}
set2 = {6, 7}
print(set1.issuperset(set2))

"""
symmetric_difference 函数用于取 setname1 和 setname2 中互不相同的元素，给 setname3，语法格式为：setname3 = setname1.symmetric_difference(setname2)，print(setname3)
"""
set1 = {4, 5, 6, 7}
set2 = {6, 7, 8}
set3 = set1.symmetric_difference(set2)
print(set3)

"""
symmetric_difference_update 函数用于取 setname1 和 setname2 中互不相同的元素，更新给 setname1，语法格式为：setname1.symmetric_difference_update(setname2)，print(setname1)
"""
set1 = {4, 5, 6, 7}
set2 = {6, 7, 8}
set1.symmetric_difference_update(set2)
print(set1)

for a in range(1, 10):
    b = 1
    while a >= b:
        print("%d*%d=%d" % (a, b, a * b), end="\t")
        b += 1
    print(end="\n")


print_1('函数',True)
print_1('可变长参数')
"""

可变长参数是指长度（数量）可变的参数，函数参数不可知的时候，就需要写一个可变长参数的函数。

（1）可变长参数在形参的作用

如果此时有一串数据要传入函数，不知道有多少个，那么应该如何定义函数呢？

① *args

可以接受多余的位置参数，并将多余参数转换成元组类型赋值给 * 后面的形参 args（* 后的形参名约定俗成为 args）。

位置参数只能多，不能少；
定义可变长形参时，*args 要放在位置参数后面。
"""
def print_obj(a, b, *args):
    print(a, b, args)
print_obj(1, 2, 3)
print_obj(1, 2, 3, 4, 5, 6)

"""
 **kwargs
 可以接受多余的关键字参数，并将多余参数转换成字典类型赋值给 ** 后面的形参 kwargs（** 后的形参名约定俗成为 kwargs）。

位置参数要对应；
多余的参数必须要用关键字传参；
定义可变长形参时，**kwargs 要放在位置参数后面。
"""
def print_obj(a, b, **kwargs):
    print(a, b, kwargs)
print_obj(1, 2)
print_obj(1, 2, c=3)
print_obj(1, 2, c=3, d=4, e=5, f=6)






